﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Runtime.InteropServices;


namespace ControlMachine
{
    public class PCSCDLL
    {
        /// <summary>
        /// 加载动态库
        /// </summary>
        /// <param name="dllName">动态库名称</param>
        /// <returns>动态库入口指针</returns>
        [DllImport("kernel32.dll")]
        public static extern IntPtr LoadLibrary(string dllName);

        /// <summary>
        /// 获取动态库中方法地址
        /// </summary>
        /// <param name="hModule">动态库加载地址</param>
        /// <param name="procedureName">方法名</param>
        /// <returns>方法地址</returns>
        [DllImport("kernel32.dll")]
        public static extern IntPtr GetProcAddress(IntPtr hModule, string procedureName);

        /// <summary>
        /// 释放动态库
        /// </summary>
        /// <param name="hModule">动态库加载地址</param>
        /// <returns>释放是否成功</returns>
        [DllImport("kernel32.dll")]
        public static extern bool FreeLibrary(IntPtr hModule);


        public enum SCARD_SCPOE : int
        {
            USER = 0x00000000,
            TERMAINAL = 0x00000001,
            SYSTEM = 0x00000002
        }

        public class SCARD_IO_REQUEST
        {
            public int dwProtocol;
            public int cbPciLength;
        }

        /// <summary>
        /// 创建读卡器设备管理上下文
        /// </summary>
        /// <param name="dwScope">读卡器可使用范围，SCARD_SCPOE.USER为当前用户,
        /// TERMAINAL未知，SYSTEM为当前系统所有用户</param>
        /// <param name="reserverd1">保留，必须为0</param>
        /// <param name="reserverd2">保留，必须为0</param>
        /// <param name="hContext">传入传出参数，设备管理器句柄</param>
        /// <returns></returns>
        [DllImport("WinSCard.dll")]
        public static extern int SCardEstablishContext(UInt32 dwScope
                                                      , int reserverd1
                                                      , int reserverd2
                                                      , out int hContext);

        /// <summary>
        /// 返回读卡设备列表
        /// </summary>
        /// <param name="hContext">设备管理器句柄</param>
        /// <param name="mszGroups">没什么用的参数，送null就好</param>
        /// <param name="mszReaders">设备名称集合</param>
        /// <param name="mszReadersSize">设备名称集合总长度</param>
        /// <returns>如果返回为0，则代表获取读卡设备成功</returns>
        [DllImport("WinSCard.dll")]
        public static extern int SCardListReaders(int hContext
                                                , byte[] mszGroups
                                                , byte[] mszReaders
                                                , ref int mszReadersSize);

        /// <summary>
        /// 卡片连接
        /// </summary>
        /// <param name="hContext">设备句柄</param>
        /// <param name="szReader">读卡器名称</param>
        /// <param name="dwShareMode">卡片公用模式</param>
        /// <param name="dwProtocols">协议使用模式</param>
        /// <param name="hCard">卡连接句柄</param>
        /// <param name="activeProtocol">卡运行协议</param>
        /// <returns></returns>
        [DllImport("WinSCard.dll")]
        public static extern int SCardConnect(int hContext
                                             , string szReader
                                             , int dwShareMode
                                             , int dwProtocols
                                             , ref int hCard
                                             , ref int activeProtocol);

        /// <summary>
        /// 设置卡片状态
        /// </summary>
        /// <param name="hCard">卡片句柄</param>
        /// <param name="szReaderName">设备名称</param>
        /// <param name="hContent">设备句柄</param>
        /// <param name="pdwState">卡片所处状态</param>
        /// <param name="pdwProtocol">卡片使用的协议</param>
        /// <param name="ATR">ATR字串</param>
        /// <param name="length">ATR字串长度</param>
        /// <returns></returns>
        [DllImport("WinSCard.dll")]
        public static extern int SCardStatus(int hCard
                                            , string szReaderName
                                            , ref int hContent
                                            , ref int pdwState
                                            , ref int pdwProtocol
                                            , byte[] ATR
                                            , ref int length);


        /// <summary>
        /// 向卡片发送数据
        /// </summary>
        /// <param name="hCard">卡片句柄</param>
        /// <param name="pioSendPci">指令的协议头结构的指针</param>
        /// <param name="pbSendBuffer">写卡数据</param>
        /// <param name="cbSendLength">写卡数据长度</param>
        /// <param name="pioRecvPci"></param>
        /// <param name="pbRecvBuffer">返回数据</param>
        /// <param name="pcbRecvLength"></param>
        /// <returns></returns>
        [DllImport("WinSCard.dll")]
        public static extern int SCardTransmit(
                                 int hCard,
                                 IntPtr pioSendPci,
                                 byte[] pbSendBuffer,
                                 int cbSendLength,
                                 SCARD_IO_REQUEST pioRecvPci,
                                 byte[] pbRecvBuffer,
                                 ref int pcbRecvLength
            );


        /// <summary>
        /// 释放连接
        /// </summary>
        /// <param name="hCard">调用SCardConnect获得的引用值</param>
        /// <param name="dwDisposition">
        /// SCARD_LEAVE_CARD = 0;对卡不做任何操作
        /// SCARD_RESET_CARD = 1;卡复位
        /// SCARD_UNPOWER_CARD = 2;对卡断电
        /// SCARD_EJECT_CARD = 3; 弹出卡
        /// </param>
        /// <returns>
        /// </returns>
        [DllImport("WinSCard.dll")]
        public static extern int SCardDisconnect(
                                 int hCard,
                                 int dwDisposition
            );

        /// <summary>
        /// 释放资源
        /// </summary>
        /// <param name="hContext">资源句柄</param>
        /// <returns></returns>
        [DllImport("WinSCard.dll")]
        public static extern int SCardReleaseContext(
                                 int hContext
            );

        [DllImport("WinSCard.dll")]
        public static extern int SCardBeginTransaction(int hContext);

    }
}
